package com.xiaolu.xiaoluaicodebackend.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.RegexPool;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.ReUtil;
import cn.hutool.core.util.StrUtil;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import com.xiaolu.xiaoluaicodebackend.constant.CacheKeyConstant;
import com.xiaolu.xiaoluaicodebackend.constant.UserConstant;
import com.xiaolu.xiaoluaicodebackend.exception.BusinessException;
import com.xiaolu.xiaoluaicodebackend.exception.ErrorCode;
import com.xiaolu.xiaoluaicodebackend.manager.message.EmailManager;
import com.xiaolu.xiaoluaicodebackend.model.dto.user.UserQueryRequest;
import com.xiaolu.xiaoluaicodebackend.model.entity.User;
import com.xiaolu.xiaoluaicodebackend.mapper.UserMapper;
import com.xiaolu.xiaoluaicodebackend.model.vo.LoginUserVO;
import com.xiaolu.xiaoluaicodebackend.model.vo.UserVO;
import com.xiaolu.xiaoluaicodebackend.service.UserService;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;
import com.xiaolu.xiaoluaicodebackend.model.enums.UserRoleEnum;

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 用户 服务层实现。
 *
 * @author <a href="https://github.com/xiaolu236532">小鹿程序员</a>
 */
@Slf4j
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User>  implements UserService{


    @Resource
    private EmailManager emailManager;

    @Resource
    private StringRedisTemplate stringRedisTemplate; //redis缓存操作



    @Override
    public long userRegister(String userEmail, String codeKey, String codeValue) {
        //1.邮箱验证码校验
        String KEY = String.format(CacheKeyConstant.EMAIL_CODE_KEY, codeKey, userEmail);
        ValueOperations<String, String> valueOps = stringRedisTemplate.opsForValue();
        String code = valueOps.get(KEY);

        //如果查询验证码为空 和 验证码不正确 则报错
        if (StrUtil.isEmpty(code)||!code.equals(codeValue)){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"验证码错误");
        }

        // 2. 检查是否重复
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.eq("userEmail", userEmail);
        long count = this.mapper.selectCountByQuery(queryWrapper);
        if (count > 0) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "账号已存在，请直接登录！");
        }
        // 3. 加密 默认密码
        String encryptPassword = getEncryptPassword("12345678");
        // 4. 插入数据
        User user = new User();
        String random = RandomUtil.randomString(6);
        user.setUserAccount("user_" + random);
        user.setUserPassword(encryptPassword);
        user.setUserName("用户_" + random);
        user.setUserEmail(userEmail);
        user.setUserRole(UserRoleEnum.USER.getValue());
        boolean saveResult = this.save(user);

        if (saveResult){
            //删除验证码
            stringRedisTemplate.delete(KEY);
            emailManager.sendEmailAsRegisterSuccess(userEmail,"鹿悦AI零代码 - 注册成功通知");
        }else {
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "注册失败，数据库错误");
        }
        return user.getId();
    }

    @Override
    public String sendEmailCode(String userEmail) {
        //校验是否存在邮箱

        // 发送邮箱验证码
        String code = RandomUtil.randomNumbers(4);
        emailManager.sendEmailCode(userEmail, "鹿悦AI零代码生成 - 注册验证码", code);
        // 生成一个唯一 ID, 后面注册前端需要带过来
        String key = UUID.randomUUID().toString();
        // 存入 Redis, 5 分钟过期
        ValueOperations<String, String> valueOps = stringRedisTemplate.opsForValue();
        valueOps.set(String.format(CacheKeyConstant.EMAIL_CODE_KEY, key, userEmail),code,5, TimeUnit.MINUTES);
        return key;
    }



    @Override
    public LoginUserVO userLogin(String userAccount, String userPassword, String captchaKey, String captchaCode, HttpServletRequest request) {
        //0.验证码校验
        //获取验证码
//        String KEY = String.format(CacheKeyConstant.CAPTCHA_CODE_KEY, captchaKey);
//        ValueOperations<String, String> valueOps = stringRedisTemplate.opsForValue();
//        String code = valueOps.get(KEY);
//        //删除验证码
//        stringRedisTemplate.delete(KEY);
        //如果没有缓存 并且 但当前的验证码信息补正确 那么就报错 （测试阶段不需要验证码）
//        if (StrUtil.isEmpty(code)||!code.equals(captchaCode)){
//            throw new BusinessException(ErrorCode.PARAMS_ERROR,"验证码错误");
//        }
        //1.校验
        if (StrUtil.hasBlank(userAccount,userPassword)){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"参数为空");
        }
        if (userAccount.length()<4){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"账号错误");
        }
        if (userPassword.length()<8){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"密码错误");
        }


        //2.加密
        String encryptPassword = getEncryptPassword(userPassword);

        //3.查询用户存在
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.eq("userPassword",encryptPassword);
        if (ReUtil.isMatch(RegexPool.EMAIL, userAccount)){ //判断输入的是不是邮箱格式
            //根据邮件获取用户信息
            queryWrapper.eq("userEmail",userAccount);
        }else {
            //根据用户名获取用户信息
            queryWrapper.eq("userAccount",userAccount);
        }
        User user = this.mapper.selectOneByQuery(queryWrapper);

        if (user==null){
            log.info("user login failed");
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"用户名或密码不存在");
        }

        //4.记录登录状态
        request.getSession().setAttribute(UserConstant.USER_LOGIN_STATE, user);
        return LoginUserVO.ObjToVo(user);
    }


    @Override
    public User getLoginUser(HttpServletRequest request) {
        //1.先判断是否登录
        Object userObject = request.getSession().getAttribute(UserConstant.USER_LOGIN_STATE);
        User currentUser=(User) userObject;
        if (currentUser==null || currentUser.getId()==null){
            throw new BusinessException(ErrorCode.NOT_LOGIN_ERROR);
        }
        //2.根据已经登录的用户id，在数据查询(为什么不直接返回上边存在的用户信息，因为如果用户修改了信息，此时上边的信息并没有及时更新)
        Long userId = currentUser.getId();
        currentUser = this.getById(userId);
        return currentUser;
    }


    @Override
    public boolean userLogout(HttpServletRequest request) {
        //1.判断当前用户是否登录
        Object userObj = request.getSession().getAttribute(UserConstant.USER_LOGIN_STATE);
        User currentUser=(User)userObj;
        if (currentUser==null || currentUser.getId()==null){
            throw new BusinessException(ErrorCode.NOT_LOGIN_ERROR);
        }
        //2.移除登录状态
        request.getSession().removeAttribute(UserConstant.USER_LOGIN_STATE);
        return true;
    }



    @Override
    public List<UserVO> getUserVoList(List<User> userList) {
        //为空，那么就返回一个空ArrayList集合
        if (CollUtil.isEmpty(userList)){
            return new ArrayList<>();
        }
//        return userList.stream().map(user->UserVO.ObjToVo(user)).collect(Collectors.toList());
        return userList.stream().map(UserVO::ObjToVo).collect(Collectors.toList());

    }


    @Override
    public QueryWrapper getQueryWrapper(UserQueryRequest userQueryRequest) {
        if (userQueryRequest == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "请求参数为空");
        }
        Long id = userQueryRequest.getId();
        String userAccount = userQueryRequest.getUserAccount();
        String userName = userQueryRequest.getUserName();
        String userProfile = userQueryRequest.getUserProfile();
        String userRole = userQueryRequest.getUserRole();
        String sortField = userQueryRequest.getSortField();
        String sortOrder = userQueryRequest.getSortOrder();
        return QueryWrapper.create()
                .eq("id", id)
                .eq("userRole", userRole)
                .like("userAccount", userAccount)
                .like("userName", userName)
                .like("userProfile", userProfile)
                .orderBy(sortField, "ascend".equals(sortOrder));
    }


    @Override
    public UserVO getUserVO(User user) {
        if (user == null) {
            return null;
        }
        UserVO userVO = new UserVO();
        BeanUtil.copyProperties(user, userVO);
        return userVO;
    }



    @Override
    public boolean isAdmin(User user) {
        //判空(不能为空)  并且 判断传进来的用户是否属于管理员
        return user!=null && UserRoleEnum.ADMIN.getValue().equals(user.getUserRole());
    }



    @Override
    public String getEncryptPassword(String userPassword) {
        // 盐值，混淆密码
        final String SALT = "xiaolu";
        return DigestUtils.md5DigestAsHex((SALT + userPassword).getBytes());
    }
}
